﻿using System;
using System.Collections;
using System.Configuration;
using System.Data;
using System.Web;
using System.Web.Security;
using System.Xml;

/// <summary>
/// Code-behind for query.aspx
/// </summary>
public partial class query : System.Web.UI.Page
{
    /// <summary>
    /// Creates sample response data to aid in the testing of our team's project
    /// </summary>
    /// <param name="doc">The document that will be returned</param>
    /// <returns>An array of XmlElement nodes representing the response data</returns>
    private XmlElement[] CreateSampleData(XmlDocument doc)
    {
        XmlElement[] resp = new XmlElement[3];

        // and for each response add it
        resp[0] = doc.CreateElement("Population");
        resp[0].SetAttribute("id", "0");
        XmlElement resp1value = doc.CreateElement("Value");
        resp1value.AppendChild(doc.CreateTextNode("0.445"));
        XmlElement resp1error = doc.CreateElement("Error");
        resp[0].AppendChild(resp1value);
        resp[0].AppendChild(resp1error);

        resp[1] = doc.CreateElement("Population");
        resp[1].SetAttribute("id", "1");
        XmlElement resp2value = doc.CreateElement("Value");
        resp2value.AppendChild(doc.CreateTextNode("0.11345"));
        XmlElement resp2error = doc.CreateElement("Error");
        resp[1].AppendChild(resp2value);
        resp[1].AppendChild(resp2error);

        resp[2] = doc.CreateElement("Population");
        resp[2].SetAttribute("id", "2");
        XmlElement resp3value = doc.CreateElement("Value");
        XmlElement resp3error = doc.CreateElement("Error");
        resp3error.AppendChild(doc.CreateTextNode("Invalid Comparison"));
        resp[2].AppendChild(resp3value);
        resp[2].AppendChild(resp3error);

        return resp;
    }

    /// <summary>
    /// Called when the page is requested.  Akin to Main() for this page
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void Page_Load(object sender, EventArgs e)
    {
        // in all cases we will be returning an XML document
        Response.ContentType = "text/xml";

        // create the document we will return
        XmlDocument reply = new XmlDocument();
        XmlElement response = reply.CreateElement("Response");
        reply.AppendChild(response);

        // report either no error (<Error/>) or an error
        XmlElement errorElement = reply.CreateElement("Error");
        response.AppendChild(errorElement);

        try
        {
            XmlElement[] elements = null;

            // if no query is specified, return sample data
            string query = Request.QueryString["q"];
            if (query != null)
                elements = ProcessRequest(reply, query);
            else
            {
                // provide an alternate method of querying per Terry's request
                string loc = Request.QueryString["location"];
                string cs = Request.QueryString["coupleStatus"];
                string comp = Request.QueryString["compare"];
                string eth = Request.QueryString["ethnicity"];
                if (loc != null || cs != null || comp != null || eth != null)
                {
                    // don't worry about escaping here.  If the data results in an invalid document we will error
                    // out later on.  "Injecting" xml data into this document won't cause any problems either... worst
                    // case it will just return more values!
                    string xml = "<Request><Population id=\"0\">" +
                        "<Location>" + loc + "</Location>" +
                        "<CoupleStatus>" + cs + "</CoupleStatus>" +
                        "<Ethnicity>" + eth + "</Ethnicity>" +
                        "<Compare>" + comp + "</Compare>" +
                    "</Population></Request>";
                    elements = ProcessRequest(reply, xml);
                }   
                else
                    elements = CreateSampleData(reply);
            }

            // Add the returned elements to the document
            foreach (XmlElement ele in elements)
                response.AppendChild(ele);
        }
        catch (Exception ex)
        {   
            // report an error if an exception is thrown.  The default error page will mess up ajax
            errorElement.AppendChild(reply.CreateTextNode(ex.GetType().Name + ": " + ex.Message));
        }

        // write out the XML response
        XmlTextWriter xw = new XmlTextWriter(Response.Output);
        xw.Formatting = Formatting.Indented;
        reply.WriteTo(xw);
        xw.Flush();
    }
    
    /// <summary>
    /// Processes a user request.  If an exception is thrown, it is handled by the Page_Load
    /// method and returned in an appropriate manner to the user.
    /// </summary>
    /// <param name="doc">The XMLDocument used to create the child elements</param>
    /// <param name="queryXML">The XML query provided by the client</param>
    /// <returns>a list of XmlElement elements for each query result</returns>
    private XmlElement[] ProcessRequest(XmlDocument doc, string queryXML)
    {
        ClientRequest req = new ClientRequest();

        // load the client's query
        XmlDocument query = new XmlDocument();
        query.LoadXml(queryXML);

        // for each population in the query, add it to the clientrequest
        XmlNodeList inputpops = query.DocumentElement.GetElementsByTagName("Population");
        foreach (XmlElement pop in inputpops)
            req.AddPopulation(new Population(pop));

        // process it.  Here's where the database access takes place
        req.Process();

        // for each population create an XmlElement to pass on its result
        XmlElement[] pops = new XmlElement[req.Populations.Count];
        for (int i = 0; i < req.Populations.Count; i++)
            pops[i] = req.Populations[i].ToXML(doc);

        return pops;
    }
}
